home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 September (Japanese) / CICA Shareware for Windows CD-ROM (Walnut Creek) (September 1995) (Japanese) (Disc 2).iso / disc2 / nt / source.exe / POSIX / ELVIS / JUNK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-16  |  17.7 KB  |  918 lines

  1. /* tio.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains terminal I/O functions */
  12.  
  13. #include "config.h"
  14. #if BSD || COHERENT
  15. # include <setjmp.h>
  16. #endif
  17. #include <signal.h>
  18. #include "vi.h"
  19. //#include "curses.h"
  20.  
  21. #ifdef DF_POSIX
  22. #include <stdio.h>
  23. #include <stdarg.h>
  24. #endif
  25.  
  26. /* This function reads in a line from the terminal. */
  27. int vgets(prompt, buf, bsize)
  28.     char    prompt;    /* the prompt character, or '\0' for none */
  29.     char    *buf;    /* buffer into which the string is read */
  30.     int    bsize;    /* size of the buffer */
  31. {
  32.     int    len;    /* how much we've read so far */
  33.     int    ch;    /* a character from the user */
  34.     int    quoted;    /* is the next char quoted? */
  35.     int    tab;    /* column position of cursor */
  36.     char    widths[132];    /* widths of characters */
  37. #ifndef NO_DIGRAPH
  38.     int    erased;    /* 0, or first char of a digraph */
  39. #endif
  40.  
  41.     /* show the prompt */
  42.     move(LINES - 1, 0);
  43.     tab = 0;
  44.     if (prompt)
  45.     {
  46.         addch(prompt);
  47.         tab = 1;
  48.     }
  49.     clrtoeol();
  50.     refresh();
  51.  
  52.     /* read in the line */
  53. #ifndef NO_DIGRAPH
  54.     erased =
  55. #endif
  56.     quoted = len = 0;
  57.     for (;;)
  58.     {
  59.         ch = getkey(quoted ? 0 : WHEN_EX);
  60.  
  61.         /* some special conversions */
  62.         if (ch == ctrl('D') && len == 0)
  63.             ch = ctrl('[');
  64. #ifndef NO_DIGRAPH
  65.         if (*o_digraph && erased != 0 && ch != '\b')
  66.         {
  67.             ch = digraph(erased, ch);
  68.             erased = 0;
  69.         }
  70. #endif
  71.  
  72.         /* inhibit detection of special chars (except ^J) after a ^V */
  73.         if (quoted && ch != '\n')
  74.         {
  75.             ch |= 256;
  76.         }
  77.  
  78.         /* process the character */
  79.         switch(ch)
  80.         {
  81.           case ctrl('V'):
  82.             qaddch('^');
  83.             qaddch('\b');
  84.             quoted = TRUE;
  85.             break;
  86.  
  87.           case ctrl('['):
  88.             return -1;
  89.  
  90.           case '\n':
  91. #if OSK
  92.           case '\l':
  93. #else
  94.           case '\r':
  95. #endif
  96.             clrtoeol();
  97.             goto BreakBreak;
  98.  
  99.           case '\b':
  100.             if (len > 0)
  101.             {
  102.                 len--;
  103. #ifndef NO_DIGRAPH
  104.                 erased = buf[len];
  105. #endif
  106.                 for (ch = widths[len]; ch > 0; ch--)
  107.                     addch('\b');
  108.                 if (mode == MODE_EX)
  109.                 {
  110.                     clrtoeol();
  111.                 }
  112.                 tab -= widths[len];
  113.             }
  114.             else
  115.             {
  116.                 return -1;
  117.             }
  118.             break;
  119.  
  120.           default:
  121.             /* strip off quotation bit */
  122.             if (ch & 256)
  123.             {
  124.                 ch &= ~256;
  125.                 quoted = FALSE;
  126.                 qaddch(' ');
  127.                 qaddch('\b');
  128.             }
  129.             /* add & echo the char */
  130.             if (len < bsize - 1)
  131.             {
  132.                 if (ch == '\t')
  133.                 {
  134.                     widths[len] = *o_tabstop - (tab % *o_tabstop);
  135.                     addstr("        " + 8 - widths[len]);
  136.                     tab += widths[len];
  137.                 }
  138.                 else if (ch > 0 && ch < ' ') /* > 0 by GB */
  139.                 {
  140.                     addch('^');
  141.                     addch(ch + '@');
  142.                     widths[len] = 2;
  143.                     tab += 2;
  144.                 }
  145.                 else if (ch == '\177')
  146.                 {
  147.                     addch('^');
  148.                     addch('?');
  149.                     widths[len] = 2;
  150.                     tab += 2;
  151.                 }
  152.                 else
  153.                 {
  154.                     addch(ch);
  155.                     widths[len] = 1;
  156.                     tab++;
  157.                 }
  158.                 buf[len++] = ch;
  159.             }
  160.             else
  161.             {
  162.                 beep();
  163.             }
  164.         }
  165.     }
  166. BreakBreak:
  167.     refresh();
  168.     buf[len] = '\0';
  169.     return len;
  170. }
  171.  
  172.  
  173. /* ring the terminal's bell */
  174. void beep()
  175. {
  176.     if (*o_vbell)
  177.     {
  178.         do_VB();
  179.         refresh();
  180.     }
  181.     else if (*o_errorbells)
  182.     {
  183.         ttywrite("\007", 1);
  184.     }
  185. }
  186.  
  187. static int    manymsgs; /* This variable keeps msgs from overwriting each other */
  188. static char    pmsg[80]; /* previous message (waiting to be displayed) */
  189.  
  190.  
  191. static int showmsg()
  192. {
  193.     /* if there is no message to show, then don't */
  194.     if (!manymsgs)
  195.         return FALSE;
  196.  
  197.     /* display the message */
  198.     move(LINES - 1, 0);
  199.     if (*pmsg)
  200.     {
  201.         standout();
  202.         qaddch(' ');
  203.         qaddstr(pmsg);
  204.         qaddch(' ');
  205.         standend();
  206.     }
  207.     clrtoeol();
  208.  
  209.     manymsgs = FALSE;
  210.     return TRUE;
  211. }
  212.  
  213.  
  214. void endmsgs()
  215. {
  216.     if (manymsgs)
  217.     {
  218.         showmsg();
  219.         addch('\n');
  220.     }
  221. }
  222.  
  223. /* Write a message in an appropriate way.  This should really be a varargs
  224.  * function, but there is no such thing as vwprintw.  Hack!!!
  225.  *
  226.  * In MODE_EX or MODE_COLON, the message is written immediately, with a
  227.  * newline at the end.
  228.  *
  229.  * In MODE_VI, the message is stored in a character buffer.  It is not
  230.  * displayed until getkey() is called.  msg() will call getkey() itself,
  231.  * if necessary, to prevent messages from being lost.
  232.  *
  233.  * msg("")        - clears the message line
  234.  * msg("%s %d", ...)    - does a printf onto the message line
  235.  */
  236. /*VARARGS1*/
  237.  
  238. #ifdef DF_POSIX
  239. void MSG(char *fmt, ... )
  240. {
  241.     long    arg1, arg2, arg3, arg4, arg5, arg6, arg7;
  242.     va_list    marker;
  243.     long param;
  244.  
  245.     va_start( marker, fmt);
  246.     
  247.     for (count=1, param = va_arg( marker, char *);
  248.             param != -1;
  249.             param = va_arg( marker, long), count++) {
  250.         switch (count) {
  251.           case 1: arg1 = param; break;
  252.           case 2: arg2 = param; break;
  253.           case 3: arg3 = param; break;
  254.           case 4: arg4 = param; break;
  255.           case 5: arg5 = param; break;
  256.           case 6: arg6 = param; break;
  257.           case 7: arg7 = param; break;
  258.         }
  259.     }
  260.  
  261.     va_end( marker );
  262.  
  263.     if (mode != MODE_VI)
  264.     {
  265.         sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  266.         qaddstr(pmsg);
  267.         addch('\n');
  268.         exrefresh();
  269.     }
  270.     else
  271.     {
  272.         /* wait for keypress between consecutive msgs */
  273.         if (manymsgs)
  274.         {
  275.             getkey(WHEN_MSG);
  276.         }
  277.  
  278.         /* real message */
  279.         sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  280.         manymsgs = TRUE;
  281.     }
  282. }
  283. #else
  284. void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
  285.     char    *fmt;
  286.     long    arg1, arg2, arg3, arg4, arg5, arg6, arg7;
  287. {
  288.     if (mode != MODE_VI)
  289.     {
  290.         sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  291.         qaddstr(pmsg);
  292.         addch('\n');
  293.         exrefresh();
  294.     }
  295.     else
  296.     {
  297.         /* wait for keypress between consecutive msgs */
  298.         if (manymsgs)
  299.         {
  300.             getkey(WHEN_MSG);
  301.         }
  302.  
  303.         /* real message */
  304.         sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  305.         manymsgs = TRUE;
  306.     }
  307. }
  308. #endif
  309.  
  310.  
  311. /* This function calls refresh() if the option exrefresh is set */
  312. void exrefresh()
  313. {
  314.     char    *scan;
  315.  
  316.     /* If this ex command wrote ANYTHING set exwrote so vi's  :  command
  317.      * can tell that it must wait for a user keystroke before redrawing.
  318.      */
  319.     for (scan=kbuf; scan<stdscr; scan++)
  320.         if (*scan == '\n')
  321.             exwrote = TRUE;
  322.  
  323. #if MICROSOFT            /* avoid compiler bug */
  324.     scan = stdscr;
  325. #define    stdscr    scan
  326. #endif
  327.     /* now we do the refresh thing */
  328.     if (*o_exrefresh)
  329.     {
  330.         refresh();
  331.     }
  332.     else
  333.     {
  334.         wqrefresh(stdscr);
  335.     }
  336. #if MICROSOFT
  337. #undef    stdscr
  338.     stdscr = scan;
  339. #endif
  340.     if (mode != MODE_VI)
  341.     {
  342.         manymsgs = FALSE;
  343.     }
  344. }
  345.  
  346.  
  347.  
  348. /* These are used for typeahead, and also for fudging the visual @ command */
  349. static char    keybuf[100];    /* array of already-read keys */
  350. static int    nkeys;        /* total number of keys in keybuf */
  351. static int    next;        /* index of next key to return */
  352. #ifndef NO_AT
  353. static int    atnext;        /* index of next key for "@", or 0 normally */
  354. int fromcutbuf(cbname)
  355.     int    cbname;
  356. {
  357.     int    len;
  358.  
  359.     /* fail if we're already doing an @ macro */
  360.     if (atnext > 0 && keybuf[atnext])
  361.     {
  362.         msg("Can't nest @ commands");
  363.         return FALSE;
  364.     }
  365.  
  366.     /* use the empty portion of keybuf[] to get chars from the cut buffer */
  367.     len = cb2str(cbname, keybuf + nkeys, sizeof keybuf - nkeys);
  368.     if (len < 0)
  369.     {
  370.         msg("Invalid cut buffer name.  Must be a-z");
  371.         return FALSE;
  372.     }
  373.     if (len == 0)
  374.     {
  375.         msg("Cut buffer \"%c is empty", cbname);
  376.         return FALSE;
  377.     }
  378.     else if (len >= sizeof keybuf - nkeys)
  379.     {
  380.         msg("Cut buffer \"%c is too large to execute", cbname);
  381.         return FALSE;
  382.     }
  383.  
  384.     /* prepare to "read" those keys on subsequent getkey() calls */
  385.     atnext = nkeys;
  386.     return TRUE;
  387. }
  388. #endif
  389.  
  390. /* This array describes mapped key sequences */
  391. static struct _keymap
  392. {
  393.     char    *name;        /* name of the key, or NULL */
  394.     char    rawin[LONGKEY];    /* the unmapped version of input */
  395.     char    cooked[80];    /* the mapped version of input */
  396.     int    len;        /* length of the unmapped version */
  397.     int    when;        /* when is this key mapped? */
  398. }
  399.     mapped[MAXMAPS];
  400.  
  401. #if !MSDOS && !TOS
  402. # if BSD || COHERENT
  403. static jmp_buf env_timeout;
  404. static int dummy()
  405. {
  406.     longjmp(env_timeout, 1);
  407.     return 0;
  408. }
  409. # else 
  410. static int dummy()
  411. {
  412. }
  413. # endif
  414. #endif
  415.  
  416. /* This function reads in a keystroke for VI mode.  It automatically handles
  417.  * key mapping.
  418.  */
  419. int getkey(when)
  420.     int        when;        /* which bits must be ON? */
  421. {
  422.     static char    *cooked;    /* rawin, or pointer to converted key */ 
  423.     static int    oldwhen;    /* "when" from last time */
  424.     static int    oldleft;
  425.     static long    oldtop;
  426.     static long    oldnlines;
  427.     static char    *cshape;    /* current cursor shape */
  428.     REG char    *kptr;        /* &keybuf[next] */
  429.     REG struct _keymap *km;    /* used to count through keymap */
  430.     REG int        i, j, k;
  431.  
  432. #ifdef DEBUG
  433.     watch();
  434. #endif
  435.  
  436.     /* if this key is needed for delay between multiple error messages,
  437.      * then reset the manymsgs flag and abort any mapped key sequence.
  438.      */
  439.     if (showmsg())
  440.     {
  441.         if (when == WHEN_MSG)
  442.         {
  443.             qaddstr("[More...]");
  444.             refresh();
  445.             cooked = (char *)0;
  446.         }
  447.         else if (when == WHEN_VIINP || when == WHEN_VIREP)
  448.         {
  449.             redraw(cursor, TRUE);
  450.         }
  451.     }
  452.  
  453. #ifndef NO_AT
  454.     /* if we're in the middle of a visual @ macro, take atnext */
  455.     if (atnext > 0)
  456.     {
  457.         if (keybuf[atnext])
  458.         {
  459.             return keybuf[atnext++];
  460.         }
  461.         atnext = 0;
  462.     }
  463. #endif
  464.  
  465.     /* if we're doing a mapped key, get the next char */
  466.     if (cooked && *cooked)
  467.     {
  468.         return *cooked++;
  469.     }
  470.  
  471.     /* if keybuf is empty, fill it */
  472.     if (next == nkeys)
  473.     {
  474. #ifndef NO_CURSORSHAPE
  475.         /* make sure the cursor is the right shape */
  476.         if (has_CQ)
  477.         {
  478.             cooked = cshape;
  479.             switch (when)
  480.             {
  481.               case WHEN_EX:        cooked = CX;    break;
  482.               case WHEN_VICMD:    cooked = CV;    break;
  483.               case WHEN_VIINP:    cooked = CI;    break;
  484.               case WHEN_VIREP:    cooked = CR;    break;
  485.             }
  486.             if (cooked != cshape)
  487.             {
  488.                 cshape = cooked;
  489.                 switch (when)
  490.                 {
  491.                   case WHEN_EX:        do_CX();    break;
  492.                   case WHEN_VICMD:    do_CV();    break;
  493.                   case WHEN_VIINP:    do_CI();    break;
  494.                   case WHEN_VIREP:    do_CR();    break;
  495.                 }
  496.             }
  497.             cooked = (char *)0;
  498.         }
  499. #endif
  500.  
  501. #ifndef NO_SHOWMODE
  502.         /* if "showmode" then say which mode we're in */
  503.         if (*o_smd
  504.          && mode == MODE_VI
  505.          && (when != oldwhen || topline != oldtop || leftcol != oldleft || nlines != oldnlines))
  506.         {
  507.             oldwhen = when;
  508.             oldtop = topline;
  509.             oldleft = leftcol;
  510.             oldnlines = nlines;
  511.  
  512.             if (when & WHEN_VICMD)
  513.             {
  514.                 redraw(cursor, FALSE);
  515.                 move(LINES - 1, COLS - 10);
  516.                 standout();
  517.                 addstr("Command");
  518.                 standend();
  519.                 redraw(cursor, FALSE);
  520.             }
  521.             else if (when & WHEN_VIINP)
  522.             {
  523.                 redraw(cursor, TRUE);
  524.                 move(LINES - 1, COLS - 10);
  525.                 standout();
  526.                 addstr(" Input ");
  527.                 standend();
  528.                 redraw(cursor, TRUE);
  529.             }
  530.             else if (when & WHEN_VIREP)
  531.             {
  532.                 redraw(cursor, TRUE);
  533.                 move(LINES - 1, COLS - 10);
  534.                 standout();
  535.                 addstr("Replace");
  536.                 standend();
  537.                 redraw(cursor, TRUE);
  538.             }
  539.         }
  540.         else
  541. #endif
  542.  
  543.         /* redraw if getting a VI command */
  544.         if (when & WHEN_VICMD)
  545.         {
  546.             redraw(cursor, FALSE);
  547.         }
  548.  
  549.         /* read the rawin keystrokes */
  550.         refresh();
  551.         while ((nkeys = ttyread(keybuf, sizeof keybuf)) < 0)
  552.         {
  553.             /* terminal was probably resized */
  554.             *o_lines = LINES;
  555.             *o_columns = COLS;
  556.             if (when & (WHEN_VICMD|WHEN_VIINP|WHEN_VIREP))
  557.             {
  558.                 redraw(MARK_UNSET, FALSE);
  559.                 redraw(cursor, (when & WHEN_VICMD) == 0);
  560.                 refresh();
  561.             }
  562.         }
  563.         next = 0;
  564.  
  565.         /* if nkeys == 0 then we've reached EOF of an ex script. */
  566.         if (nkeys == 0)
  567.         {
  568.             tmpabort(TRUE);
  569.             move(LINES - 1, 0);
  570.             clrtoeol();
  571.             refresh();
  572.             endwin();
  573.             exit(1);
  574.         }
  575.     }
  576.  
  577.     /* see how many mapped keys this might be */
  578.     kptr = &keybuf[next];
  579.     for (i = j = 0, k = -1, km = mapped; i < MAXMAPS; i++, km++)
  580.     {
  581.         if ((km->when & when) && km->len > 0 && *km->rawin == *kptr)
  582.         {
  583.             if (km->len > nkeys - next)
  584.             {
  585.                 if (!strncmp(km->rawin, kptr, nkeys - next))
  586.                 {
  587.                     j++;
  588.                 }
  589.             }
  590.             else
  591.             {
  592.                 if (!strncmp(km->rawin, kptr, km->len))
  593.                 {
  594.                     j++;
  595.                     k = i;
  596.                 }
  597.             }
  598.         }
  599.     }
  600.  
  601.     /* if more than one, try to read some more */
  602.     while (j > 1)
  603.     {
  604. #if BSD || COHERENT
  605.         if (setjmp(env_timeout))
  606.         {
  607.             /* we timed out - assume no mapping */
  608.             j = 0;
  609.             break;
  610.         }
  611. #endif
  612. #if ANY_UNIX || DF_POSIX
  613.         signal(SIGALRM, dummy);
  614. #endif
  615. #if OSK
  616.         signal(SIGQUIT, dummy);
  617. #endif
  618.         alarm((unsigned)*o_keytime);
  619.         i = nkeys;
  620.         if ((k = ttyread(keybuf + nkeys, sizeof keybuf - nkeys)) >= 0)
  621.         {
  622.             nkeys += k;
  623.         }
  624.         alarm(0);
  625. #if OSK
  626. # ifndef DEBUG
  627.         signal(SIGQUIT, SIG_IGN);
  628. # endif
  629. #endif
  630.  
  631.         /* if we couldn't read any more, pretend 0 mapped keys */
  632.         if (i == nkeys)
  633.         {
  634.             j = 0;
  635.         }
  636.         else /* else we got some more - try again */
  637.         {
  638.             for (i = j = 0, k = -1, km = mapped; i < MAXMAPS; i++, km++)
  639.             {
  640.                 if ((km->when & when) && km->len > 0 && *km->rawin == *kptr)
  641.                 {
  642.                     if (km->len > nkeys - next)
  643.                     {
  644.                         if (!strncmp(km->rawin, kptr, nkeys - next))
  645.                         {
  646.                             j++;
  647.                         }
  648.                     }
  649.                     else
  650.                     {
  651.                         if (!strncmp(km->rawin, kptr, km->len))
  652.                         {
  653.                             j++;
  654.                             k = i;
  655.                         }
  656.                     }
  657.                 }
  658.             }
  659.         }
  660.     }
  661.  
  662.     /* if unambiguously mapped key, use it! */
  663.     if (j == 1 && k >= 0)
  664.     {
  665.         next += mapped[k].len;
  666.         cooked = mapped[k].cooked;
  667. #ifndef NO_EXTENSIONS
  668.         if ((when & (WHEN_VIINP|WHEN_VIREP))
  669.          && (mapped[k].when & WHEN_INMV))
  670.         {
  671.             return 0; /* special case, means "a movement char follows" */
  672.         }
  673.         else
  674. #endif
  675.         {
  676.             return *cooked++;
  677.         }
  678.     }
  679.     else
  680.     /* assume key is unmapped, but still translate weird erase key to '\b' */
  681.     if (keybuf[next] == ERASEKEY && when != 0)
  682.     {
  683.         next++;
  684.         return '\b';
  685.     }
  686.     else if (keybuf[next] == '\0')
  687.     {
  688.         next++;
  689.         return ('A' & 0x1f);
  690.     }
  691.     else
  692.     {
  693.         return keybuf[next++];
  694.     }
  695. }
  696.  
  697.  
  698. /* This function maps or unmaps a key */
  699. void mapkey(rawin, cooked, when, name)
  700.     char    *rawin;    /* the input key sequence, before mapping */
  701.     char    *cooked;/* after mapping */
  702.     short    when;    /* bitmap of when mapping should happen */
  703.     char    *name;    /* name of the key, if any */
  704. {
  705.     int    i, j;
  706.  
  707. #ifndef NO_EXTENSIONS
  708.     /* if the mapped version starts with the word "visual" then set WHEN_INMV */
  709.     if (!strncmp(cooked, "visual ", 7))
  710.     {
  711.         when |= WHEN_INMV;
  712.         cooked += 7;
  713.     }
  714.     /* if WHEN_INMV is set, then WHEN_VIINP and WHEN_VIREP must be set */
  715.     if (when & WHEN_INMV)
  716.     {
  717.         when |= (WHEN_VIINP | WHEN_VIREP);
  718.     }
  719. #endif
  720.  
  721.     /* see if the key sequence was mapped before */
  722.     j = strlen(rawin);
  723.     for (i = 0; i < MAXMAPS; i++)
  724.     {
  725.         if (mapped[i].len == j
  726.          && !strncmp(mapped[i].rawin, rawin, j)
  727.          && (mapped[i].when & when))
  728.         {
  729.             break;
  730.         }
  731.     }
  732.  
  733.     /* if not already mapped, then try to find a new slot to use */
  734.     if (i == MAXMAPS)
  735.     {
  736.         for (i = 0; i < MAXMAPS && mapped[i].len > 0; i++)
  737.         {
  738.         }
  739.     }
  740.  
  741.     /* no room for the new key? */
  742.     if (i == MAXMAPS)
  743.     {
  744.         msg("No room left in the key map table");
  745.         return;
  746.     }
  747.  
  748.     /* map the key */
  749.     if (cooked && *cooked)
  750.     {
  751.         /* Map the key */
  752.         mapped[i].len = j;
  753.         strncpy(mapped[i].rawin, rawin, j);
  754.         strcpy(mapped[i].cooked, cooked);
  755.         mapped[i].when = when;
  756.         mapped[i].name = name;
  757.     }
  758.     else /* unmap the key */
  759.     {
  760.         mapped[i].len = 0;
  761.     }
  762. }
  763.  
  764. /* Dump keys of a given type - WHEN_VICMD dumps the ":map" keys, and
  765.  * WHEN_VIINP|WHEN_VIREP dumps the ":map!" keys
  766.  */
  767. void dumpkey(when)
  768.     int    when;    /* WHEN_XXXX of mappings to be dumped */
  769. {
  770.     int    i, len, mlen;
  771.     char    *scan;
  772.     char    *mraw;
  773.  
  774.     for (i = 0; i < MAXMAPS; i++)
  775.     {
  776.         /* skip unused entries, or entries that don't match "when" */
  777.         if (mapped[i].len <= 0 || !(mapped[i].when & when))
  778.         {
  779.             continue;
  780.         }
  781.  
  782.         /* dump the key label, if any */
  783.         len = 8;
  784.         if (mapped[i].name)
  785.         {
  786.             qaddstr(mapped[i].name);
  787.             len -= strlen(mapped[i].name);
  788.         }
  789.         do
  790.         {
  791.             qaddch(' ');
  792.         } while (len-- > 0);
  793.  
  794.         /* dump the raw version */
  795.         len = 0;
  796.         mlen = mapped[i].len;
  797.         mraw = mapped[i].rawin;
  798.         for (scan = mraw; scan < mraw + mlen; scan++)
  799.         {
  800.             if (UCHAR(*scan) < ' ' || *scan == '\177')
  801.             {
  802.                 qaddch('^');
  803.                 qaddch(*scan ^ '@');
  804.                 len += 2;
  805.             }
  806.             else
  807.             {
  808.                 qaddch(*scan);
  809.                 len++;
  810.             }
  811.         }
  812.         do
  813.         {
  814.             qaddch(' ');
  815.         } while (++len < 8);
  816.  
  817.         /* dump the mapped version */
  818. #ifndef NO_EXTENSIONS
  819.         if ((mapped[i].when & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP)))
  820.         {
  821.             qaddstr("visual ");
  822.         }
  823. #endif
  824.         for (scan = mapped[i].cooked; *scan; scan++)
  825.         {
  826.             if (UCHAR(*scan) < ' ' || *scan == '\177')
  827.             {
  828.                 qaddch('^');
  829.                 qaddch(*scan ^ '@');
  830.             }
  831.             else
  832.             {
  833.                 qaddch(*scan);
  834.             }
  835.         }
  836.  
  837.         addch('\n');
  838.         exrefresh();
  839.     }
  840. }
  841.  
  842.  
  843.  
  844. #ifndef MKEXRC
  845. /* This function saves the current configuration of mapped keys to a file */
  846. void savekeys(fd)
  847.     int    fd;    /* file descriptor to save them to */
  848. {
  849.     int    i;
  850.     char    buf[80];
  851.  
  852.     /* now write a map command for each key other than the arrows */
  853.     for (i = 0; i < MAXMAPS; i++)
  854.     {
  855.         /* ignore keys that came from termcap */
  856.         if (mapped[i].name)
  857.         {
  858.             continue;
  859.         }
  860.  
  861.         /* If this isn't used, ignore it */
  862.         if (mapped[i].len <= 0)
  863.         {
  864.             continue;
  865.         }
  866.  
  867.         /* write the map command */
  868. #ifndef NO_EXTENSIONS
  869.         if (mapped[i].when & WHEN_INMV)
  870.         {
  871. #if OSK
  872.             char    fmt[80];
  873.             sprintf(fmt, "map%%s %%.%ds %%s\n", mapped[i].len);
  874.             sprintf(buf, fmt,
  875.                 (mapped[i].when & WHEN_VICMD) ? "" : "!",
  876. #else
  877.             sprintf(buf, "map%s %.*s visual %s\n",
  878.                 (mapped[i].when & WHEN_VICMD) ? "" : "!",
  879.                 mapped[i].len,
  880. #endif
  881.                 mapped[i].rawin,
  882.                 mapped[i].cooked);
  883.             twrite(fd, buf, strlen(buf));
  884.         }
  885.         else
  886. #endif
  887.         {
  888.             if (mapped[i].when & WHEN_VICMD)
  889.             {
  890. #if OSK
  891.                 char    fmt[80];
  892.                 sprintf(fmt, "map %%.%ds %%s\n", mapped[i].len);
  893.                 sprintf(buf, fmt,
  894. #else
  895.                 sprintf(buf, "map %.*s %s\n", mapped[i].len,
  896. #endif
  897.                     mapped[i].rawin,
  898.                     mapped[i].cooked);
  899.                 twrite(fd, buf, strlen(buf));
  900.             }
  901.             if (mapped[i].when & (WHEN_VIINP | WHEN_VIREP))
  902.             {
  903. #if OSK
  904.                 char    fmt[80];
  905.                 sprintf(fmt, "map! %%.%ds %%s\n", mapped[i].len);
  906.                 sprintf(buf, fmt,
  907. #else
  908.                 sprintf(buf, "map! %.*s %s\n", mapped[i].len,
  909. #endif
  910.                     mapped[i].rawin,
  911.                     mapped[i].cooked);
  912.                 twrite(fd, buf, strlen(buf));
  913.             }
  914.         }
  915.     }
  916. }
  917. #endif
  918.